/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package scm.rawMaterialPurchasing.session;

import crm.salesOrderProcessing.entity.ProductEntity;
import crm.salesOrderProcessing.session.ProductManageSessionBean;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import mrp.productionPlanning.entity.WeeklyDetailEntity;
import scm.rawMaterialPurchasing.entity.BOMLineItemEntity;
import scm.rawMaterialPurchasing.entity.RawMaterialEntity;
import scm.rawMaterialPurchasing.entity.RawMaterialPurchasingOrderLineItemEntity;
import scm.rawMaterialPurchasing.entity.RawMaterialRequirementEntity;
import scm.rawMaterialPurchasing.entity.RawMaterialRequirementLineItemEntity;
import scm.rawMaterialPurchasing.entity.RawMaterialPurchasingOrderEntity;

/**
 *
 * @author ReinforceII
 */
@Stateless
@LocalBean
public class RawMaterialPurchasingSessionBean {

    @PersistenceContext
    EntityManager em;
    @EJB
    ProductManageSessionBean productManagementSessionBean;
    RawMaterialRequirementEntity rawMaterialRequirement;
    List<RawMaterialRequirementLineItemEntity> resultBOMLineItems;
    ProductEntity productA;
    ProductEntity productB;
    ProductEntity productC;
    ProductEntity productD;

    public RawMaterialPurchasingSessionBean() {
        
    }

    public void generateWeeklyRawMaterialRequirementList(Date date) {

        rawMaterialRequirement = new RawMaterialRequirementEntity();
        resultBOMLineItems = new ArrayList();
        productA = productManagementSessionBean.getProductById(1l);
        productB = productManagementSessionBean.getProductById(2l);
        productC = productManagementSessionBean.getProductById(3l);
        productD = productManagementSessionBean.getProductById(4l);


        Date startDate = getStartDate(date);
        Date endDate = getEndDate(date);

        boolean flag1 = false;
        boolean flag2 = false;
        boolean flag3 = false;

        System.out.println(startDate);

        Query query = em.createQuery("SELECT wde FROM WeeklyDetailEntity wde WHERE wde.date >= :startDate AND wde.date <= :endDate");
        query.setParameter("startDate", startDate); //later try to select only needed records from database using the following lines.
        query.setParameter("endDate", endDate);



        List<WeeklyDetailEntity> weeklyDetailList = query.getResultList();

        assert (weeklyDetailList.size() == 3); //Make sure we have 3 weeklyDetails, for test purpose.


        for (WeeklyDetailEntity w : weeklyDetailList) {
            System.out.println(w.getDate());
        }

        Calendar c = Calendar.getInstance();
        c.setTime(startDate);
        c.add(Calendar.DAY_OF_MONTH, 2);
        startDate = c.getTime();

        c.setTime(endDate);
        c.add(Calendar.DAY_OF_MONTH, -2);
        endDate = c.getTime();

        for (WeeklyDetailEntity weeklyDetail : weeklyDetailList) {

            if (weeklyDetail.getDate().before(startDate) && !flag1) { //Means this is the detail for next week

                addLineItems(weeklyDetail, 1);
                flag1 = true;
            } else if (weeklyDetail.getDate().after(endDate) && !flag3) { //Means this is the detail for 3 weeks later
                addLineItems(weeklyDetail, 3);
                flag3 = true;
            } else if (!flag2) { //Means this is the detail for 2 weeks later and it is the first time entering here
                addLineItems(weeklyDetail, 2);
                flag2 = true;
            }


        }

        assert (flag1 && flag2 && flag3);
        
        Date MondayOfThisWeek = getMondayOfThisWeek(date);

        rawMaterialRequirement.setRawMaterialRequirementLineItems(resultBOMLineItems);
        rawMaterialRequirement.setDateGenerated(Calendar.getInstance().getTime());
        rawMaterialRequirement.setForWeekStartingOn(MondayOfThisWeek);
        rawMaterialRequirement.setPurchasingOrderGenerated(false);

        em.persist(rawMaterialRequirement);

    }

    private void addLineItems(WeeklyDetailEntity weeklyDetail, int week) {

        if (weeklyDetail.getScheduleA() > 0) {

            List<BOMLineItemEntity> productBOMLineItemList = productA.getBillOfMaterials().getBomLineItems();
            for (BOMLineItemEntity bom : productBOMLineItemList) {

                if (bom.getRawMaterial().getLeadTime() == week) {

                    boolean newLineItem = true;
                    for (RawMaterialRequirementLineItemEntity lineItem : resultBOMLineItems) {
                        if (lineItem.getRawMaterial().equals(bom.getRawMaterial())) {
                            newLineItem = false;
                            lineItem.setQuantity(lineItem.getQuantity() + (bom.getQuantity() * weeklyDetail.getScheduleA()));
                            break;
                        }
                    }

                    if (newLineItem) {

                        RawMaterialRequirementLineItemEntity lineItem = new RawMaterialRequirementLineItemEntity();
                        lineItem.setQuantity(bom.getQuantity() * weeklyDetail.getScheduleA());
                        lineItem.setRawMaterial(bom.getRawMaterial());
                        resultBOMLineItems.add(lineItem);
                    }


                }
            }

        }

        if (weeklyDetail.getScheduleB() > 0) {

            List<BOMLineItemEntity> productBOMLineItemList = productB.getBillOfMaterials().getBomLineItems();
            for (BOMLineItemEntity bom : productBOMLineItemList) {

                if (bom.getRawMaterial().getLeadTime() == week) {

                    boolean newLineItem = true;
                    for (RawMaterialRequirementLineItemEntity lineItem : resultBOMLineItems) {
                        if (lineItem.getRawMaterial().equals(bom.getRawMaterial())) {
                            newLineItem = false;
                            lineItem.setQuantity(lineItem.getQuantity() + (bom.getQuantity() * weeklyDetail.getScheduleB()));
                            break;
                        }
                    }

                    if (newLineItem) {

                        RawMaterialRequirementLineItemEntity lineItem = new RawMaterialRequirementLineItemEntity();
                        lineItem.setQuantity(bom.getQuantity() * weeklyDetail.getScheduleB());
                        lineItem.setRawMaterial(bom.getRawMaterial());
                        resultBOMLineItems.add(lineItem);
                    }


                }
            }

        }
        if (weeklyDetail.getScheduleC() > 0) {

            List<BOMLineItemEntity> productBOMLineItemList = productC.getBillOfMaterials().getBomLineItems();
            for (BOMLineItemEntity bom : productBOMLineItemList) {

                if (bom.getRawMaterial().getLeadTime() == week) {

                    boolean newLineItem = true;
                    for (RawMaterialRequirementLineItemEntity lineItem : resultBOMLineItems) {
                        if (lineItem.getRawMaterial().equals(bom.getRawMaterial())) {
                            newLineItem = false;
                            lineItem.setQuantity(lineItem.getQuantity() + (bom.getQuantity() * weeklyDetail.getScheduleC()));
                            break;
                        }
                    }

                    if (newLineItem) {

                        RawMaterialRequirementLineItemEntity lineItem = new RawMaterialRequirementLineItemEntity();
                        lineItem.setQuantity(bom.getQuantity() * weeklyDetail.getScheduleC());
                        lineItem.setRawMaterial(bom.getRawMaterial());
                        resultBOMLineItems.add(lineItem);
                    }


                }
            }

        }

        if (weeklyDetail.getScheduleD() > 0) {

            List<BOMLineItemEntity> productBOMLineItemList = productD.getBillOfMaterials().getBomLineItems();
            for (BOMLineItemEntity bom : productBOMLineItemList) {

                if (bom.getRawMaterial().getLeadTime() == week) {

                    boolean newLineItem = true;
                    for (RawMaterialRequirementLineItemEntity lineItem : resultBOMLineItems) {
                        if (lineItem.getRawMaterial().equals(bom.getRawMaterial())) {
                            newLineItem = false;
                            lineItem.setQuantity(lineItem.getQuantity() + (bom.getQuantity() * weeklyDetail.getScheduleD()));
                            break;
                        }
                    }

                    if (newLineItem) {

                        RawMaterialRequirementLineItemEntity lineItem = new RawMaterialRequirementLineItemEntity();
                        lineItem.setQuantity(bom.getQuantity() * weeklyDetail.getScheduleD());
                        lineItem.setRawMaterial(bom.getRawMaterial());
                        resultBOMLineItems.add(lineItem);
                    }


                }
            }

        }


    }
    public void updateRawMaterial(RawMaterialRequirementEntity rawMaterialRequirementEntity){
        em.merge(rawMaterialRequirementEntity);
        em.flush();
    }
    public List<RawMaterialPurchasingOrderEntity> getAllRawMaterialPurchasingOrder(){
        Query query = em.createQuery("SELECT u FROM RawMaterialPurchasingOrderEntity u");
        return query.getResultList();
        
    }
    public void addRawMaterialPurchaseOrder(RawMaterialPurchasingOrderEntity rawMaterialPurchasingOrder) {
        double price = 0;
        for(int i=0;i<rawMaterialPurchasingOrder.getRawMaterialPurchasingOrderLineItems().size();i++){
            price = price + rawMaterialPurchasingOrder.getRawMaterialPurchasingOrderLineItems().get(i).getCumAmount();
        }
        em.persist(rawMaterialPurchasingOrder);

    }
    
    private Date getMondayOfThisWeek(Date date){
        
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int daysPastThisMonday;
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            daysPastThisMonday = -6;
        } else {
            daysPastThisMonday = 2 - c.get(Calendar.DAY_OF_WEEK);
        }
        c.add(Calendar.DAY_OF_MONTH, daysPastThisMonday);
        Date result = c.getTime();

        return result;
    }

    private Date getStartDate(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int daysUntilNextWeek;
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            daysUntilNextWeek = 1;
        } else {
            daysUntilNextWeek = 9 - c.get(Calendar.DAY_OF_WEEK);
        }
        c.add(Calendar.DAY_OF_MONTH, daysUntilNextWeek - 1);
        Date result = c.getTime();

        return result;
    }

    private Date getEndDate(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int daysUntilNextWeek;
        if (c.get(Calendar.DAY_OF_WEEK) == 1) {
            daysUntilNextWeek = 15;
        }

        daysUntilNextWeek = 23 - c.get(Calendar.DAY_OF_WEEK);
        c.add(Calendar.DAY_OF_MONTH, daysUntilNextWeek + 1);
        Date result = c.getTime();

        return result;
    }

    public List<RawMaterialRequirementEntity> getAllRawMaterialRequirements() {

        Query query = em.createQuery("SELECT rmre FROM RawMaterialRequirementEntity rmre WHERE rmre.purchasingOrderGenerated = 0");

        return query.getResultList();
    }
        public List<RawMaterialRequirementEntity> getAllTheRawMaterialRequirements() {

        Query query = em.createQuery("SELECT rmre FROM RawMaterialRequirementEntity rmre WHERE rmre.purchasingOrderGenerated = 1");

        return query.getResultList();
    }
    public List<RawMaterialEntity> getAllRawMaterial(){
       Query query = em.createQuery("SELECT u from RawMaterialEntity u");
       return query.getResultList();
    }
    
    public List<RawMaterialPurchasingOrderEntity> getRawMaterialPurchasingOrdersForWeek(Date date) {

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, -1);
        Date startDate = c.getTime();
        c.add(Calendar.DAY_OF_MONTH, 6);
        Date endDate = c.getTime();
        
        Query query = em.createQuery("SELECT rmre FROM RawMaterialPurchasingOrderEntity rmre WHERE rmre.dateGenerated > :startDate AND rmre.dateGenerated < :endDate");
        query.setParameter("startDate", startDate);
        query.setParameter("endDate", endDate);

        return query.getResultList();
    }

    public boolean isAllMaterialReceived(Long purchasingOrderId) {

        RawMaterialPurchasingOrderEntity purchasingOrder = em.find(RawMaterialPurchasingOrderEntity.class, purchasingOrderId);


        boolean allReceived = true;

        for (RawMaterialPurchasingOrderLineItemEntity item : purchasingOrder.getRawMaterialPurchasingOrderLineItems()) {
            if (!item.isReceived()) {
                allReceived = false;
            }
        }

        return allReceived;
    }

    public void recptionOfMaterial(Long id) {

        RawMaterialPurchasingOrderLineItemEntity lineItem;

        lineItem = em.find(RawMaterialPurchasingOrderLineItemEntity.class, id);

        if (lineItem == null) {
            System.out.println("RawMaterialPurchasingSessionBean: this id points to a null value.");
        }

        lineItem.setReceived(true);

        em.merge(lineItem);

    }
    
    public List<RawMaterialPurchasingOrderEntity> getAllPurchasingOrders(){
        
        Query query = em.createQuery("SELECT rmre FROM RawMaterialPurchasingOrderEntity rmre");
        
        return query.getResultList();
    }

    public RawMaterialPurchasingOrderEntity getRawMaterialPurchasingOrderById(Long selectedId) {
        return em.find(RawMaterialPurchasingOrderEntity.class, selectedId);
    }
}
